using Ke.Bee.Shared.Abstractions;
using Ke.Bee.Shared.Models;
using Ke.Bee.Shared.Models.Uploads;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Ke.Bee.Shared.Impl;

/// <summary>
/// 文件存储服务
/// </summary>
public class FileStorageService : IFileStorageService
{
    private readonly ILogger<FileStorageService> _logger;
    private readonly UploadOptions _uploadOptions;

    public FileStorageService(ILogger<FileStorageService> logger, IOptions<UploadOptions> options)
    {
        _logger = logger;
        _uploadOptions = options.Value;
    }

    /// <summary>
    /// 保存临时文件
    /// </summary>
    /// <param name="file"></param>
    /// <param name="ct"></param>
    /// <returns></returns>
    public async Task<ApiResponse<FileStorageResult>> SaveTemporaryFileAsync(IFormFile? file, string taskId, CancellationToken ct)
    {
        if (file is null)
        {
            return ApiResponse<FileStorageResult>.Fail("未选择文件");
        }

        if (file.Length == 0)
        {
            return ApiResponse<FileStorageResult>.Fail("文件为空");
        }

        try
        {
            // 验证文件扩展名
            var fileExtension = Path.GetExtension(file.FileName).ToLower();
            if (!_uploadOptions.AllowedExtensions.Contains(fileExtension))
            {
                return ApiResponse<FileStorageResult>.Fail($"不支持的文件格式: {fileExtension}");
            }

            // 验证文件大小 (500MB)
            if (file.Length > _uploadOptions.MaxFileSize)
            {
                return ApiResponse<FileStorageResult>.Fail($"文件大小不能超过 {_uploadOptions.MaxFileSize}MB");
            }

            var fileName = $"{taskId}{fileExtension}";
            var filePath = Path.Combine(_uploadOptions.UploadPath, fileName);

            await using var stream = new FileStream(filePath, FileMode.Create);
            await file.CopyToAsync(stream, ct);

            var r = new FileStorageResult(taskId,
                filePath,
                file.FileName,
                file.Length,
                file.ContentType,
                DateTimeOffset.UtcNow)
                ;

            return ApiResponse<FileStorageResult>.Ok(data: r);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "保存临时文件失败: {FileName}", file.FileName);
            return ApiResponse<FileStorageResult>.Fail($"文件保存失败: {ex.Message}");
        }
    }

    public async Task<bool> DeleteFileAsync(string filePath, CancellationToken ct)
    {
        try
        {
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
                _logger.LogInformation("文件已删除: {FilePath}", filePath);
            }
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "删除文件失败: {FilePath}", filePath);
            return false;
        }
    }

    public async Task CleanupOldFilesAsync(TimeSpan olderThan, CancellationToken ct)
    {
        try
        {
            var cutoffTime = DateTimeOffset.UtcNow - olderThan;
            var files = Directory.GetFiles(_uploadOptions.TempDirectory)
                .Select(f => new FileInfo(f))
                .Where(f => f.LastWriteTimeUtc < cutoffTime);

            foreach (var file in files)
            {
                await DeleteFileAsync(file.FullName, ct);
            }

            _logger.LogInformation("清理了 {FileCount} 个过期临时文件", files.Count());
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "清理临时文件失败");
        }
    }
}